home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / printing / std file saver / source / mypdef_0_draftmode.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  23.4 KB  |  862 lines

  1. /*
  2. ** Copyright 1991-1996 Apple Computer. All rights reserved.
  3. **
  4. **    You may incorporate this sample code into your applications without
  5. **    restriction, though the sample code has been provided "AS IS" and the
  6. **    responsibility for its operation is 100% yours.  However, what you are
  7. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  8. **    after having made changes. If you're going to re-distribute the source,
  9. **    we require that you make it clear in the source that the code was
  10. **    descended from Apple Sample Code, but that you've made changes.
  11. */
  12.  
  13. #include <stddef.h>
  14. #include <types.h>
  15.  
  16. #include <Printing.h>
  17. #include <Memory.h>
  18. #include <Files.h>
  19. #include <Resources.h>
  20. #include <TextUtils.h>
  21. #include <StandardFile.h>
  22. #include <Events.h>
  23.  
  24. #include "driverTypes.h"
  25. #include "StringUtils.h"
  26. #include "FileUtils.h"
  27. #include "SettingsUtils.h"
  28.  
  29. pascal TPPrPort DraftPrOpenDoc(THPrint hPrint, TPPrPort pPrPort, Ptr pIOBuf);
  30. pascal void DraftPrCloseDoc(TPPrPort pPrPort);
  31. pascal void DraftPrOpenPage(TPPrPort pPrPort, TPRect pPageFrame);
  32. pascal void DraftPrClosePage(TPPrPort pPrPort);
  33.  
  34. #if defined(__MWERKS__)
  35. asm void __Startup__ (void);
  36. asm void __Startup__ (void)
  37. {
  38.     JMP    DraftPrOpenDoc
  39.     JMP    DraftPrCloseDoc
  40.     JMP    DraftPrOpenPage
  41.     JMP    DraftPrClosePage
  42. }
  43. #endif
  44.  
  45. /*******************************************************************************
  46.     Constants for the Command-period checker.
  47. *******************************************************************************/
  48. #define    kModifiersMask        0xFF00 & ~cmdKey    /*    We need all modifiers
  49.                                                     except the command key
  50.                                                     for KeyTrans. */
  51. #define    kOtherCharCodeMask    0x00FF0000            /*    Get the key out of the
  52.                                                     ASCII1 byte. */
  53.  
  54. static Boolean IsColorGrafPort(GrafPtr thePort)
  55. {
  56.     return(thePort->portBits.rowBytes < 0);
  57. }
  58.  
  59. static void GetEventChars(EventRecord *theEvent, long *lowChar, long *highChar)
  60. {
  61.     unsigned    long    state = 0;
  62.     long                keyInfo;
  63.     long                virtualKey = (theEvent->message & keyCodeMask) >> 8;
  64.     long                keyCID    = GetScript(GetEnvirons(smKeyScript), smScriptKeys);
  65.     Handle                hKCHR    = GetResource('KCHR', keyCID);
  66.     unsigned    short    keyCode    = (theEvent->modifiers & kModifiersMask) | virtualKey;
  67.  
  68.     if (hKCHR != nil) {
  69.         HLock(hKCHR);
  70.         keyInfo = KeyTranslate((void *)(*hKCHR), keyCode, &state);
  71.         HUnlock(hKCHR);
  72.         ReleaseResource( hKCHR );
  73.     } else {
  74.         keyInfo = theEvent->message;
  75.     }
  76.  
  77.     *lowChar =  keyInfo & charCodeMask;
  78.     *highChar = (keyInfo & kOtherCharCodeMask) >> 16;
  79. }
  80.  
  81. static Boolean CmdPeriod(EventRecord *theEvent)
  82. {
  83.     Boolean  result;
  84.  
  85.     if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
  86.         long    lowChar, highChar;
  87.         GetEventChars(theEvent, &lowChar, &highChar);
  88.  
  89.         if ((theEvent->modifiers & cmdKey) != 0 ) {
  90.             result = ((lowChar == period) || (highChar == period));
  91.         } else {
  92.             result = ((lowChar == escape) || (highChar == escape));
  93.         }
  94.     } else result = false;    // it wasn't my kind of event
  95.  
  96.     return result;
  97. }
  98.  
  99. static void MyIdleProc(void)
  100. {
  101.     const short mask = (keyDownMask | autoKeyMask);
  102.     EventRecord    theEvent;
  103.     
  104.     if (EventAvail(mask,&theEvent)) {
  105.         if (CmdPeriod(&theEvent)) {
  106.             (void)GetNextEvent(mask,&theEvent);    // eat the event
  107.             setPrintErr(iPrAbort);
  108.         }
  109.     }
  110. }
  111.  
  112. static void CallIdleProc(PrIdleUPP idleProc)
  113. {
  114.     if (idleProc)
  115.         CallPrIdleProc(idleProc);
  116.     else
  117.         MyIdleProc();
  118. }
  119.  
  120. pascal void DraftPrText(short byteCount, Ptr textBuf, Point numer, Point denom)
  121. {
  122. #pragma unused(numer)
  123. #pragma unused(denom)
  124.  
  125.     GrafPtr pPrPort;
  126.     MyPrintPtr myPrintRecord;
  127.  
  128. #ifdef TRACKING
  129.     DebugStr("\pin DraftPrText;g");
  130. #endif
  131.  
  132.     GetPort(&pPrPort);
  133.  
  134.     // don't need to worry about rgnSave or polySave for text
  135.  
  136.     myPrintRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  137.  
  138.     BlockMoveData(pPrPort, myPrintRecord->OtherPort, mostOfGrafPort);
  139.     SetPort(myPrintRecord->OtherPort);
  140.     // do scaling here
  141.     DrawText(textBuf, 0, byteCount);
  142.     CallIdleProc(myPrintRecord->idleProc);
  143.     SetPort(pPrPort);
  144.     // adjust the pen location for scaling
  145. }
  146.  
  147. pascal void DraftPrLine(Point newPt)
  148. {
  149.     GrafPtr pPrPort;
  150.     MyPrintPtr printRecord;
  151.  
  152. #ifdef TRACKING
  153.     DebugStr("\pin DraftPrLine;g");
  154. #endif
  155.  
  156.     GetPort(&pPrPort);
  157.  
  158.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  159.  
  160.     // if rgnSave field of grafPort is non-nil, don't change port,
  161.     // since that screws up region recording, same goes for polySave
  162.     if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
  163.         StdLine(newPt);
  164.     } else {
  165.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  166.         SetPort(printRecord->OtherPort);
  167.         // do scaling here
  168.         LineTo(newPt.h, newPt.v);
  169.         SetPort(pPrPort);
  170.         pPrPort->pnLoc = newPt;    // set the pen location correctly
  171.     }
  172.     CallIdleProc(printRecord->idleProc);
  173. }
  174.  
  175. pascal void DraftPrRect(GrafVerb verb, RectPtr r)
  176. {
  177.     GrafPtr pPrPort;
  178.     MyPrintPtr printRecord;
  179.  
  180. #ifdef TRACKING
  181.     DebugStr("\pin DraftPrRect;g");
  182. #endif
  183.  
  184.     GetPort(&pPrPort);
  185.  
  186.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  187.  
  188.     // if rgnSave field of grafPort is non-nil, don't change port,
  189.     // since that screws up region recording, same goes for polySave
  190.     if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
  191.         StdRect(verb,r);
  192.     } else {
  193.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  194.         SetPort(printRecord->OtherPort);
  195.         // do scaling here
  196.         switch (verb) { 
  197.             case frame:
  198.                 FrameRect(r);
  199.                 break;
  200.             case paint:
  201.                 PaintRect(r);
  202.                 break;
  203.             case erase:
  204.                 EraseRect(r);
  205.                 break;
  206.             case invert:
  207.                 InvertRect(r);
  208.                 break;
  209.             case fill:
  210.                 FillRect(r, &printRecord->OtherPort->fillPat);
  211.                 break;
  212.             default:
  213.                 DebugStr("\pUnknown verb for rect");
  214.                 break;
  215.         }
  216.         SetPort(pPrPort);
  217.     }
  218.     CallIdleProc(printRecord->idleProc);
  219. }
  220.  
  221. pascal void DraftPrrRect(GrafVerb verb, Rect * r, short ovalWidth, short ovalHeight)
  222. {
  223.     GrafPtr pPrPort;
  224.     MyPrintPtr printRecord;
  225.  
  226. #ifdef TRACKING
  227.     DebugStr("\pin DraftPrrRect;g");
  228. #endif
  229.  
  230.     GetPort(&pPrPort);
  231.  
  232.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  233.  
  234.     // if rgnSave field of grafPort is non-nil, don't change port,
  235.     // since that screws up region recording, same goes for polySave
  236.     if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
  237.         StdRRect(verb,r,ovalWidth,ovalHeight);
  238.     } else {
  239.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  240.         SetPort(printRecord->OtherPort);
  241.         // do scaling here
  242.         switch (verb) { 
  243.             case frame:
  244.                 FrameRoundRect(r, ovalWidth, ovalHeight);
  245.                 break;
  246.             case paint:
  247.                 PaintRoundRect(r, ovalWidth, ovalHeight);
  248.                 break;
  249.             case erase:
  250.                 EraseRoundRect(r, ovalWidth, ovalHeight);
  251.                 break;
  252.             case invert:
  253.                 InvertRoundRect(r, ovalWidth, ovalHeight);
  254.                 break;
  255.             case fill:
  256.                 FillRoundRect(r, ovalWidth, ovalHeight, &printRecord->OtherPort->fillPat);
  257.                 break;
  258.             default:
  259.                 DebugStr("\pUnknown verb for RoundRect");
  260.                 break;
  261.         }
  262.         SetPort(pPrPort);
  263.     }
  264.     CallIdleProc(printRecord->idleProc);
  265. }
  266.  
  267. pascal void DraftPrOval(GrafVerb verb, Rect * r)
  268. {
  269.     GrafPtr pPrPort;
  270.     MyPrintPtr printRecord;
  271.  
  272. #ifdef TRACKING
  273.     DebugStr("\pin DraftPrOval;g");
  274. #endif
  275.  
  276.     GetPort(&pPrPort);
  277.  
  278.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  279.  
  280.     // if rgnSave field of grafPort is non-nil, don't change port,
  281.     // since that screws up region recording, same goes for polySave
  282.     if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
  283.         StdOval(verb,r);
  284.     } else {
  285.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  286.         SetPort(printRecord->OtherPort);
  287.         // do scaling here
  288.         switch (verb) { 
  289.             case frame:
  290.                 FrameOval(r);
  291.                 break;
  292.             case paint:
  293.                 PaintOval(r);
  294.                 break;
  295.             case erase:
  296.                 EraseOval(r);
  297.                 break;
  298.             case invert:
  299.                 InvertOval(r);
  300.                 break;
  301.             case fill:
  302.                 FillOval(r, &printRecord->OtherPort->fillPat);
  303.                 break;
  304.             default:
  305.                 DebugStr("\pUnknown verb for oval");
  306.                 break;
  307.         }
  308.         SetPort(pPrPort);
  309.     }
  310.     CallIdleProc(printRecord->idleProc);
  311. }
  312.  
  313. pascal void DraftPrArc(GrafVerb verb, Rect * r, short startAngle, short arcAngle)
  314. {
  315.     GrafPtr pPrPort;
  316.     MyPrintPtr printRecord;
  317.  
  318. #ifdef TRACKING
  319.     DebugStr("\pin DraftPrArc;g");
  320. #endif
  321.  
  322.     GetPort(&pPrPort);
  323.  
  324.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  325.  
  326.     // if rgnSave field of grafPort is non-nil, don't change port,
  327.     // since that screws up region recording, same goes for polySave
  328.     if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
  329.         StdArc(verb,r,startAngle,arcAngle);
  330.     } else {
  331.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  332.         SetPort(printRecord->OtherPort);
  333.         // do scaling here
  334.         switch (verb) { 
  335.             case frame:
  336.                 FrameArc(r, startAngle, arcAngle);
  337.                 break;
  338.             case paint:
  339.                 PaintArc(r, startAngle, arcAngle);
  340.                 break;
  341.             case erase:
  342.                 EraseArc(r, startAngle, arcAngle);
  343.                 break;
  344.             case invert:
  345.                 InvertArc(r, startAngle, arcAngle);
  346.                 break;
  347.             case fill:
  348.                 FillArc(r, startAngle, arcAngle, &printRecord->OtherPort->fillPat);
  349.                 break;
  350.             default:
  351.                 DebugStr("\pUnknown verb for arc");
  352.                 break;
  353.         }
  354.         SetPort(pPrPort);
  355.     }
  356.     CallIdleProc(printRecord->idleProc);
  357. }
  358.  
  359. pascal void DraftPrPoly(GrafVerb verb, PolyHandle Poly)
  360. {
  361.     GrafPtr pPrPort;
  362.     MyPrintPtr printRecord;
  363.  
  364. #ifdef TRACKING
  365.     DebugStr("\pin DraftPrPoly;g");
  366. #endif
  367.  
  368.     GetPort(&pPrPort);
  369.  
  370.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  371.  
  372.     // if rgnSave field of grafPort is non-nil, don't change port,
  373.     // since that screws up region recording
  374.     // calling poly procs with poly recording on is bad, so we won't
  375.     // even think about that possibility
  376.     if (pPrPort->rgnSave) {
  377.         StdPoly(verb,Poly);
  378.     } else {
  379.         BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  380.         SetPort(printRecord->OtherPort);
  381.         // do scaling here
  382.         switch (verb) { 
  383.             case frame:
  384.                 FramePoly(Poly);
  385.                 break;
  386.             case paint:
  387.                 PaintPoly(Poly);
  388.                 break;
  389.             case erase:
  390.                 ErasePoly(Poly);
  391.                 break;
  392.             case invert:
  393.                 InvertPoly(Poly);
  394.                 break;
  395.             case fill:
  396.                 FillPoly(Poly, &printRecord->OtherPort->fillPat);
  397.                 break;
  398.             default:
  399.                 DebugStr("\pUnknown verb for poly");
  400.                 break;
  401.         }
  402.         SetPort(pPrPort);
  403.     }
  404.     CallIdleProc(printRecord->idleProc);
  405. }
  406.  
  407. pascal void DraftPrRgn(GrafVerb verb, RgnHandle Rgn)
  408. {
  409.     GrafPtr pPrPort;
  410.     MyPrintPtr printRecord;
  411.  
  412. #ifdef TRACKING
  413.     DebugStr("\pin DraftPrRgn;g");
  414. #endif
  415.  
  416.     GetPort(&pPrPort);
  417.  
  418.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  419.  
  420.     // if rgnSave field of grafPort is non-nil, don't change port,
  421.     // since that screws up region recording, same goes for polySave
  422.     // calling poly procs with poly recording on would be
  423.     // bad enough that I'm just going to ignore it.
  424.     if (pPrPort->polySave) {
  425.         StdRgn(verb,Rgn);
  426.     } else {
  427.         BlockMoveData(pPrPort,printRecord->OtherPort, mostOfGrafPort);
  428.         SetPort(printRecord->OtherPort);
  429.         // do scaling here
  430.         switch (verb) { 
  431.             case frame:
  432.                 FrameRgn(Rgn);
  433.                 break;
  434.             case paint:
  435.                 PaintRgn(Rgn);
  436.                 break;
  437.             case erase:
  438.                 EraseRgn(Rgn);
  439.                 break;
  440.             case invert:
  441.                 InvertRgn(Rgn);
  442.                 break;
  443.             case fill:
  444.                 FillRgn(Rgn, &printRecord->OtherPort->fillPat);
  445.                 break;
  446.             default:
  447.                 DebugStr("\pUnknown region verb");
  448.                 break;
  449.         }
  450.         SetPort(pPrPort);
  451.     }
  452.     CallIdleProc(printRecord->idleProc);
  453. }
  454.  
  455. pascal void DraftPrBits(BitMapPtr srcBits, Rect * srcRect, Rect * dstRect, short mode, RgnHandle maskRgn)
  456. {
  457.     GrafPtr pPrPort;
  458.     Rect aRect;
  459.     MyPrintPtr printRecord;
  460.  
  461. #ifdef TRACKING
  462.     DebugStr("\pin DraftPrBits;g");
  463. #endif
  464.  
  465.     GetPort(&pPrPort);
  466.  
  467.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  468.  
  469.     BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  470.     SetPort(printRecord->OtherPort);
  471.     aRect = *dstRect;
  472.     // do scaling here
  473.     CopyBits(srcBits, &printRecord->OtherPort->portBits, srcRect, &aRect, mode, maskRgn);
  474.     CallIdleProc(printRecord->idleProc);
  475.     SetPort(pPrPort);
  476. }
  477.  
  478. pascal void DraftPrComment(short kind, short dataSize, Handle dataHandle)
  479. {
  480.     GrafPtr pPrPort;
  481.     MyPrintPtr printRecord;
  482.  
  483. #ifdef TRACKING
  484.     DebugStr("\pin DraftPrComment;g");
  485. #endif
  486.  
  487.     GetPort(&pPrPort);
  488.  
  489.     printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
  490.  
  491.     BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  492.     SetPort(printRecord->OtherPort);
  493.     PicComment(kind, dataSize, dataHandle);
  494.     CallIdleProc(printRecord->idleProc);
  495.     SetPort(pPrPort);
  496. }
  497.  
  498. pascal short DraftPrTxMeas(short byteCount, Ptr textAddr,
  499.     Point *numer, Point *denom, FontInfo *info)
  500. {
  501.     short    retval;
  502.  
  503. #ifdef TRACKING
  504.     DebugStr("\pin DraftPrTxMeas;g");
  505. #endif
  506.  
  507.     // If the port is scaled, you'll need to modify the values
  508.     // passed to and returned by StdTxMeas() to take the
  509.     // scaling into account
  510.     retval = StdTxMeas(byteCount,textAddr,numer,denom,info);
  511.     return retval;
  512. }
  513.  
  514. #ifdef COMPRESSED_DATA
  515. pascal void DraftPrPix(PixMapPtr src, const Rect *srcRect, MatrixRecordPtr matrix,
  516.     short mode, RgnHandle mask, PixMapPtr matte, Rect *matteRect, short flags)
  517. {
  518. #pragma unused(src)
  519. #pragma unused(srcRect)
  520. #pragma unused(matrix)
  521. #pragma unused(mode)
  522. #pragma unused(mask)
  523. #pragma unused(matte)
  524. #pragma unused(matteRect)
  525. #pragma unused(flags)
  526.     // If we want to support sending compressed data, this is the
  527.     // place to hook in the support. See Develop 24, pp 72-83 for
  528.     // details. Also see IM:QuickTime pg 3-137 and IM:Imaging for
  529.     // more details. As an added benefit, CopyDeepMask comes through
  530.     // this proc, which is why the setIsPrintingFlag and
  531.     // clearIsPrintingFlag macros are commented out in the header
  532.     // file and point you to here for more explanation.
  533.     DebugStr("\pTsk. COMPRESSED_DATA flag set, but no code written.");
  534. }
  535. #endif
  536.  
  537. void SetPrgProcs(TPPrPort myPPrPort)
  538. {
  539.     // Using UPPs, since this hopes to be native some day
  540.     myPPrPort->gProcs.textProc = NewQDTextProc(DraftPrText);
  541.     myPPrPort->gProcs.lineProc = NewQDLineProc(DraftPrLine);
  542.     myPPrPort->gProcs.rectProc = NewQDRectProc(DraftPrRect);
  543.     myPPrPort->gProcs.rRectProc = NewQDRRectProc(DraftPrrRect);
  544.     myPPrPort->gProcs.ovalProc = NewQDOvalProc(DraftPrOval);
  545.     myPPrPort->gProcs.arcProc = NewQDArcProc(DraftPrArc);
  546.     myPPrPort->gProcs.polyProc = NewQDPolyProc(DraftPrPoly);
  547.     myPPrPort->gProcs.rgnProc = NewQDRgnProc(DraftPrRgn);
  548.     myPPrPort->gProcs.bitsProc = NewQDBitsProc(DraftPrBits);
  549.     myPPrPort->gProcs.commentProc = NewQDCommentProc(DraftPrComment);
  550.     myPPrPort->gProcs.txMeasProc = NewQDTxMeasProc(DraftPrTxMeas);
  551.  
  552.     // note: no bottleneck replacement for getPicProc or putPicProc
  553.     
  554.     // Note: also no pixProc bottleneck, since it ain't there unless
  555.     // it's a CGrafPort, which this ain't.
  556. }
  557.  
  558. pascal void ChangeBottleNeck(Boolean withColor, TPPrPort myPPrPort, MyPrintPtr thePrintPtr)
  559. {
  560.     if (withColor) {
  561.         OpenCPort((CGrafPtr)myPPrPort);
  562.         SetStdCProcs(&thePrintPtr->cProcs);
  563.         
  564.         // even with a Color PICT saving, we set the gProcs field of the Printing port 
  565.         // just in case some weird application wants to use them directly 
  566.         // to my knowledge, no application do such an absurd thing as that but Murphy Lives ! 
  567.         SetPrgProcs(myPPrPort);
  568.         
  569.         thePrintPtr->cProcs.textProc = NewQDTextProc(DraftPrText);
  570.         thePrintPtr->cProcs.lineProc = NewQDLineProc(DraftPrLine);
  571.         thePrintPtr->cProcs.rectProc = NewQDRectProc(DraftPrRect);
  572.         thePrintPtr->cProcs.rRectProc = NewQDRRectProc(DraftPrrRect);
  573.         thePrintPtr->cProcs.ovalProc = NewQDOvalProc(DraftPrOval);
  574.         thePrintPtr->cProcs.arcProc = NewQDArcProc(DraftPrArc);
  575.         thePrintPtr->cProcs.polyProc = NewQDPolyProc(DraftPrPoly);
  576.         thePrintPtr->cProcs.rgnProc = NewQDRgnProc(DraftPrRgn);
  577.         thePrintPtr->cProcs.bitsProc = NewQDBitsProc(DraftPrBits);
  578.         thePrintPtr->cProcs.commentProc = NewQDCommentProc(DraftPrComment);
  579.         thePrintPtr->cProcs.txMeasProc = NewQDTxMeasProc(DraftPrTxMeas);
  580. #ifdef COMPRESSED_DATA
  581.         // If we want to handle compressed data, we put in our stdPix replacement
  582.         ///// Hmm. There doesn't seem to be a declaration for a NewQDPixProc in QuickDraw.h
  583.         ///// Bummer. Radar ID#1341027. -DaveP 4/15/96
  584.         ((CGrafPort)(myPPrPort->gPort)).grafProcs->newProc1 = DraftPrPix;
  585. #endif
  586.         ((CGrafPtr)myPPrPort)->grafProcs = &(thePrintPtr->cProcs);
  587.     } else {
  588.         OpenPort((GrafPtr)myPPrPort);
  589.         SetStdProcs(&myPPrPort->gProcs);
  590.         SetPrgProcs(myPPrPort);
  591.         myPPrPort->gPort.grafProcs = &myPPrPort->gProcs;
  592.     }
  593. }
  594.  
  595. pascal TPPrPort DraftPrOpenDoc(THPrint hPrint, TPPrPort pPrPort, Ptr pIOBuf)
  596. {
  597. #pragma unused(pIOBuf)
  598.  
  599.     SysEnvRec    theWorld;
  600.     OSErr        bugOutError;
  601.     TPPrPort    myPPrPort;
  602.     THPrint        *myHPrint;
  603.     MyPrintPtr    printRecord;
  604.  
  605. #ifdef TRACKING
  606.     DebugStr("\pin DraftPrOpenDoc;g");
  607. #endif
  608.  
  609.     myHPrint = &hPrint;
  610.     if (pPrPort == NULL) {    // does the caller give us a Printing Port or do we allocate it ? 
  611.         myPPrPort = (TPPrPort)NewPtrClear(sizeof(TPrPort));
  612.         if (myPPrPort == NULL) {
  613.             bugOutError = iMemFullErr;
  614.             goto BUGOUT;
  615.         }
  616.         myPPrPort->fOurPtr = true;
  617.     } else {
  618.         myPPrPort = pPrPort;
  619.         myPPrPort->fOurPtr = false;
  620.     }
  621.     myPPrPort->lGParam1 = 0xDEADBEEF;    // a flag value showing badness
  622.     myPPrPort->lGParam2 = 0xDEADBEEF;    // a flag value showing badness
  623.     myPPrPort->lGParam3 = 0xDEADBEEF;    // a flag value showing badness
  624.     myPPrPort->lGParam4 = (long) NewPtrClear(sizeof(MyPrintRec));    // we need this space to work
  625.     if (myPPrPort->lGParam4 == 0) {
  626.         bugOutError = iMemFullErr;
  627.         goto BUGOUT;
  628.     }
  629.     
  630.     SysEnvirons(1, &theWorld);
  631.     
  632.     // the real job is here, changing the QuickDraw Bottleneck to install our printing routines 
  633.     ChangeBottleNeck(((theWorld.hasColorQD) && ((**hPrint).printX[8] == 0)),
  634.          myPPrPort, (MyPrintPtr)myPPrPort->lGParam4);
  635.     
  636.     // to prevent any real drawing, set the bounds to EmptyRect
  637.     if (IsColorGrafPort(&(myPPrPort->gPort))) {
  638.         CGrafPtr    thePort = (CGrafPtr)(&(myPPrPort->gPort));
  639.         Rect        *theRect = &((**(thePort->portPixMap)).bounds);
  640.         SetRect(theRect, 0, 0, 0, 0);
  641.     } else {
  642.         SetRect(&(myPPrPort->gPort.portBits.bounds), 0, 0, 0, 0);
  643.     }
  644.     myPPrPort->gPort.portRect = (**hPrint).prInfo.rPage;
  645.     
  646.     printRecord = (MyPrintPtr)(myPPrPort->lGParam4);
  647.     
  648.     if ((**hPrint).printX[6]) {
  649.         // just print specified range
  650.         printRecord->firstPage = (**hPrint).prJob.iFstPage;
  651.         printRecord->lastPage = (**hPrint).prJob.iLstPage;
  652.     } else {
  653.         // print all pages
  654.         printRecord->firstPage = iPrPgFst;
  655.         printRecord->lastPage = iPrPgMax;
  656.     }
  657.  
  658.     printRecord->idleProc = (**hPrint).prJob.pIdleProc;
  659.  
  660.     printRecord->OtherPort = (GrafPtr)(NewPtrClear(sizeof(GrafPort)));
  661.     if (printRecord->OtherPort == NULL) {
  662.         bugOutError = iMemFullErr;
  663.         goto BUGOUT;
  664.     }
  665.     BlockMoveData(myPPrPort, printRecord->OtherPort, mostOfGrafPort);
  666.     
  667.     bugOutError = SelectOutputFile(&(printRecord->fileSpec));
  668.     if (bugOutError != noErr) {
  669.         DebugStr("\pFailed to select");
  670.         goto BUGOUT;
  671.     }
  672.  
  673.     bugOutError = OpenOutputFile(&(printRecord->fileSpec),
  674.                                 &(printRecord->fileRef),
  675.                                 GetSavedRadioOption());
  676.     if (bugOutError != noErr) {
  677.         DebugStr("\pFailed to open");
  678.         goto BUGOUT;
  679.     }
  680.  
  681. // normal return
  682.     return myPPrPort;
  683.  
  684.  
  685. // error conditions make us come here
  686. BUGOUT:
  687.     if (myPPrPort != NULL) {
  688.         if (myPPrPort->lGParam4 != 0) {
  689.             if (!((*(*myHPrint))->printX[7] == 0)) {
  690.                 DisposePtr((Ptr)(printRecord->OtherPort));
  691.             }
  692.             DisposePtr((Ptr)printRecord);
  693.             if (IsColorGrafPort(&(myPPrPort->gPort)))
  694.                 CloseCPort((CGrafPtr)(myPPrPort));
  695.             else 
  696.                 ClosePort((GrafPtr)(myPPrPort));
  697.         }
  698.         if (myPPrPort->fOurPtr) 
  699.             DisposePtr((Ptr)(myPPrPort));
  700.     }
  701.     setPrintErr(bugOutError);
  702.     return 0L;
  703. }
  704.  
  705. static void DisposeQDBottleNeckProcs(QDProcs theOldProcs)
  706. {
  707.     DisposeRoutineDescriptor(theOldProcs.textProc);
  708.     DisposeRoutineDescriptor(theOldProcs.lineProc);
  709.     DisposeRoutineDescriptor(theOldProcs.rectProc);
  710.     DisposeRoutineDescriptor(theOldProcs.rRectProc);
  711.     DisposeRoutineDescriptor(theOldProcs.ovalProc);
  712.     DisposeRoutineDescriptor(theOldProcs.arcProc);
  713.     DisposeRoutineDescriptor(theOldProcs.polyProc);
  714.     DisposeRoutineDescriptor(theOldProcs.rgnProc);
  715.     DisposeRoutineDescriptor(theOldProcs.bitsProc);
  716.     DisposeRoutineDescriptor(theOldProcs.commentProc);
  717.     DisposeRoutineDescriptor(theOldProcs.txMeasProc);
  718. }
  719.  
  720. static void DisposeCQDBottleNeckProcs(CQDProcs theColorProcs)
  721. {
  722.     DisposeRoutineDescriptor(theColorProcs.textProc);
  723.     DisposeRoutineDescriptor(theColorProcs.lineProc);
  724.     DisposeRoutineDescriptor(theColorProcs.rectProc);
  725.     DisposeRoutineDescriptor(theColorProcs.rRectProc);
  726.     DisposeRoutineDescriptor(theColorProcs.ovalProc);
  727.     DisposeRoutineDescriptor(theColorProcs.arcProc);
  728.     DisposeRoutineDescriptor(theColorProcs.polyProc);
  729.     DisposeRoutineDescriptor(theColorProcs.rgnProc);
  730.     DisposeRoutineDescriptor(theColorProcs.bitsProc);
  731.     DisposeRoutineDescriptor(theColorProcs.commentProc);
  732.     DisposeRoutineDescriptor(theColorProcs.txMeasProc);
  733.     ///// The following gets commented in when the NewxxxxxProc macro is used
  734. #ifdef COMPRESSED_DATA
  735.     // If we want to handle compressed data, we put in our stdPix replacement
  736.     ///// Hmm. There doesn't seem to be a declaration for a NewQDPixProc in QuickDraw.h
  737.     ///// Bummer. Radar ID#1341027. -DaveP 4/15/96
  738. /////    DisposeRoutineDescriptor(grafProcs->newProc1);
  739. #endif
  740. }
  741.  
  742. pascal void DraftPrCloseDoc(TPPrPort pPrPort)
  743. {
  744. #ifdef TRACKING
  745.     DebugStr("\pin DraftPrCloseDoc;g");
  746. #endif
  747.  
  748.     if (pPrPort != NULL) {
  749.         if (pPrPort->lGParam4 != 0) {
  750.             MyPrintPtr    printRecord = (MyPrintPtr)(pPrPort->lGParam4);
  751.  
  752.             (void) CloseOutputFile(printRecord->fileRef, GetSavedRadioOption());
  753.  
  754.             // Clean up the routineDescriptors in the procs
  755.             // This is needed for PPC native drivers, which this
  756.             // isn't yet, but I put it in now so I didn't space it.
  757.             // -DaveP 4/15/96
  758.             DisposeQDBottleNeckProcs(pPrPort->gProcs);
  759.             DisposeCQDBottleNeckProcs(printRecord->cProcs);
  760.             DisposePtr((Ptr)printRecord->OtherPort);
  761.             DisposePtr((Ptr)printRecord);
  762.         } else {
  763.             DebugStr("\pThis doesn't seem to be my Print Record that I've been asked to close!");
  764.         }
  765.  
  766.         if (IsColorGrafPort((GrafPtr)pPrPort))
  767.             CloseCPort((CGrafPtr)pPrPort);
  768.         else 
  769.             ClosePort((GrafPtr)pPrPort);
  770.  
  771.         // only nuke the grafport if we made it
  772.         if (pPrPort->fOurPtr) DisposePtr((Ptr)pPrPort);
  773.     } else {
  774.         DebugStr("\pTsk. Naughty application calls PrCloseDoc with a bad port");
  775.     }
  776. }
  777.  
  778. pascal void DraftPrOpenPage(TPPrPort pPrPort, TPRect pPageFrame)
  779. {
  780. #pragma unused(pPageFrame)
  781.     // in case of PICT saving, we create a new PICT file for each page 
  782.     // the name of the PICT file is the name chosen by the user + the
  783.     // number of the page and we store that file in the folder with the
  784.     // same name that we created in DraftPrOpenDoc 
  785.  
  786.     MyPrintPtr printRecord = (MyPrintPtr)pPrPort->lGParam4;
  787.  
  788. #ifdef TRACKING
  789.     DebugStr("\pin DraftPrOpenPage;g");
  790. #endif
  791.  
  792.     printRecord->CurPage++;
  793.  
  794.     setIsPrintingFlag();
  795.  
  796.     // we reinitialize this every page, even though I'm not sure I need to
  797.     BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
  798.     printRecord->OtherPort->picSave = NULL;
  799.     printRecord->OtherPort->rgnSave = NULL;
  800.     printRecord->OtherPort->polySave = NULL;
  801.     printRecord->OtherPort->grafProcs = NULL;
  802.     SetPort(printRecord->OtherPort);
  803.     // do scaling here
  804.     printRecord->thePict = OpenPicture(&printRecord->OtherPort->portRect);
  805.     if (printRecord->thePict == NULL) {
  806.         setPrintErr(iMemFullErr);
  807.         return;
  808.     }
  809.     ClipRect(&(printRecord->OtherPort->portRect));
  810.     SetPort((GrafPtr)pPrPort);
  811. }
  812.  
  813. static CTabHandle GetPmTable(CGrafPtr thePort)
  814. {
  815.     PixMapHandle thePixMap = thePort->portPixMap;
  816.     return((**thePixMap).pmTable);
  817. }
  818.  
  819. static Boolean IsInRange(short num, short min, short max)
  820. {
  821.     return ((num >= min) && (num <= max));
  822. }
  823.  
  824. pascal void DraftPrClosePage(TPPrPort pPrPort)
  825. {
  826.     long        theCount;
  827.     MyPrintPtr    printRecord = (MyPrintPtr)(pPrPort->lGParam4);
  828.  
  829. #ifdef TRACKING
  830.     DebugStr("\pin DraftPrClosePage;g");
  831. #endif
  832.  
  833.     SetPort(printRecord->OtherPort);
  834.     ClosePicture();
  835.  
  836.     clearIsPrintingFlag();
  837.  
  838.     SetPort((GrafPtr)pPrPort);
  839.     if (IsInRange(printRecord->CurPage,printRecord->firstPage,printRecord->lastPage)) {
  840.         // the following disposes of the handle correctly, too
  841.         OSErr    writeError = WritePictData(printRecord->fileRef,
  842.                             (Handle) printRecord->thePict,
  843.                             printRecord->CurPage,
  844.                             GetSavedRadioOption());
  845.         if (writeError) {
  846.             setPrintErr(writeError);
  847.             return;
  848.         }
  849.         
  850.         // we also save the current color table as a 'clut' resource
  851.         // in the same file since a lot of Color Paint or Draw software
  852.         // use that kind of information to get the colors right
  853.         writeError = WriteCLUTData(printRecord->fileRef);
  854.         if (writeError) {
  855.             setPrintErr(writeError);
  856.             return;
  857.         }
  858.     } else {
  859.         DisposeHandle((Handle)(printRecord->thePict));
  860.     }
  861. }
  862.